#include "music.h"
#include <QUuid>
#include <QMediaPlayer>
#include <QCoreApplication>
#include <QSqlQuery>
#include <QSqlError>

Music::Music()
    :isLike(false)
    ,isHistory(false)
{

}

Music::Music(QUrl url)
    :isLike(false)
    ,isHistory(false)
    ,musicUrl(url)
{
    // 读取 url 对应的歌曲文件的信息，解析出原来的数据，包括：歌曲名称、歌曲作者、歌曲专辑、歌曲总时长
    this->musicId = QUuid::createUuid().toString();
    parseMediaMetaMusic();
}

void Music::setMusicId(const QString &musicId)
{
    this->musicId = musicId;
}

void Music::setMusicName(const QString& musicName)
{
    this->musicName = musicName;
}

void Music::setMusicSinger(const QString& musicSinger)
{
    this->musicSinger = musicSinger;
}

void Music::setMusicAlbum(const QString& musicAlbum)
{
    this->musicAlbum = musicAlbum;
}

void Music::setDuration(const qint64& duration)
{
    this->duration = duration;
}

void Music::setIsLike(bool isLike)
{
    this->isLike = isLike;
}

void Music::setIsHistory(bool isHistory)
{
    this->isHistory = isHistory;
}

void Music::setMusicUrl(const QUrl& musicUrl)
{
    this->musicUrl = musicUrl;
}

QString Music::getMusicName() const
{
    return this->musicName;
}

QString Music::getMusicSinger() const
{
    return this->musicSinger;
}

QString Music::getMusicAlbum() const
{
    return this->musicAlbum;
}

qint64 Music::getDuration() const
{
    return this->duration;
}

bool Music::getIsLike() const
{
    return this->isLike;
}

bool Music::getIsHistory() const
{
    return this->isHistory;
}

QUrl Music::getMusicUrl() const
{
    return this->musicUrl;
}

QString Music::getMusicId() const
{
    return this->musicId;
}

QString Music::getLrcFilePath()
{
    // 假定歌曲和歌词文件在同一个目录下
    QString path = this->getMusicUrl().toLocalFile();
    path.replace(".mp3", ".lrc");
    path.replace(".flac", ".lrc");
    path.replace(".mpeg", ".lrc");
    return path;
}

void Music::insertMusicToDB()
{
    QSqlQuery query;
    // 判断这个 Music 对象是否在数据库中
    // 由于我们只需要判断是否在数据库中，所以尽可能的优化查询效率，直接用 select exists 判断
    // 预加载 sql 语句：使用 ? 进行后续插入的数据
    query.prepare("select exists(select 1 from musicInfo where musicId = ?)");
    // 处理未加载 ? 的数据
    query.addBindValue(musicId);
    if(!query.exec())
    {
        qDebug() << "查询失败：" << query.lastError().text();
        return;
    }
    // 需要调用一次next，才会让我们的记录放在首行
    if(query.next())
    {
        bool isExists = query.value(0).toBool();
        if(isExists)
        {
            // Music 存在数据库中，只需要更新其中的 isLike 和 isHistory 的属性
            query.prepare("update musicInfo set isLike = ? ,isHistory = ? where musicId = ?");
            query.addBindValue(isLike?1:0);
            query.addBindValue(isHistory?1:0);
            query.addBindValue(musicId);
            if(!query.exec())
            {
                qDebug() << "更新失败：" << query.lastError().text();
                return;
            }
            qDebug() << "更新music：" << musicName << "成功！";
        }
        else
        {
            // Music 不存在数据库中，需要全部插入数据库中
            query.prepare("insert into musicInfo (musicId,musicName,musicSinger,musicAlbum,musicUrl,duration,isLike,isHistory) values \
                          (?,?,?,?,?,?,?,?)");
            query.addBindValue(musicId);
            query.addBindValue(musicName);
            query.addBindValue(musicSinger);
            query.addBindValue(musicAlbum);
            query.addBindValue(musicUrl.toLocalFile());
            query.addBindValue(duration);
            query.addBindValue(isLike?1:0);
            query.addBindValue(isHistory?1:0);
            if(!query.exec())
            {
                qDebug() << "插入失败：" << query.lastError().text();
                return;
            }
            qDebug() << "插入music" << musicName << "成功！";
        }
    }
}

void Music::parseMediaMetaMusic()
{
    QMediaPlayer mediaPlayer;
    mediaPlayer.setMedia(musicUrl);  // 加载这个歌曲
    while(!mediaPlayer.isMetaDataAvailable())  // 等待加载完成
    {
        // 如果进行死循环，那么整个 Qt 的事件循环就会卡死在这里，所以我们需要手动的进行开启Qt 的事件循环，一边检测一边进行 Qt 的背后逻辑
        QCoreApplication::processEvents();
    }
    // 加载完成之后，可以设置其所有的属性了
    this->musicName = mediaPlayer.metaData("Title").toString();
    this->musicSinger = mediaPlayer.metaData("Author").toString();
    this->musicAlbum = mediaPlayer.metaData("AlbumTitle").toString();
    this->duration = mediaPlayer.metaData("Duration").toLongLong();

    // 有些音乐是盗版的音乐，可能在上述解析的时候会解析不出来，就是成为一个空串，因此我们需要手动设置一下属性
    // 我们可以从文件的名称入手，有些文件的名称类似于：2002年的第一场雪 - 刀郎.mp3  使用 - 进行歌名和歌手的分割
    QString filename = musicUrl.fileName();
    int index = filename.indexOf('-');
    // 歌名为空
    if(this->musicName.isEmpty())
    {
        if(index != -1)
            // 截取 - 左边的文字作为歌曲名称:使用 QString::mid 函数，类似于 string::substr
            this->musicName = filename.mid(0, index);
        else
            this->musicName = filename.mid(0, filename.indexOf('.'));
    }
    // 歌手为空
    if(this->musicSinger.isEmpty())
    {
        if(index != -1)
            // 使用 trimmed 删除前缀和后缀的空格
            this->musicSinger = filename.mid(index+1, filename.indexOf('.') - index-1).trimmed();
        else
            this->musicSinger = "未知歌手";
    }
    // 专辑为空
    if(this->musicAlbum.isEmpty())
        this->musicAlbum = "未知专辑";
}
